const Bill = require('../models/Bill');
const AtomBill = require('../models/AtomBill');
const { StatusCodes } = require('http-status-codes');
const mongoose = require('mongoose');

const queryBill = async (model, funcName, query) => {
   let result = await model[funcName](query)
      .select('-fromGroup -__v')
      .populate({
         path: 'members',
         select: '_id username avatar phone',
         model: 'User',
      })
      .populate({
         path: 'category',
         select: '-__v',
         model: 'Category',
      })
      .populate({
         path: 'createdBy',
         select: 'username avatar',
         model: 'User',
      })
      .sort('-createdAt');
   return result;
};

/**
 * 获取账单
 * 组合atombill
 */
const getBills = async (req, res) => {
   let bills = await queryBill(Bill, 'find', { fromGroup: req.params.groupId });

   let atombills = await AtomBill.find({
      group: req.params.groupId,
   }).populate({
      path: 'user',
      select: '_id username',
      model: 'User',
   });
   bills = bills.map((bill) => {
      const _atombills = atombills.filter((item) =>
         item.billId.equals(bill._id)
      );
      return {
         details: _atombills.map((item) => ({
            username: item.user.username,
            userId: item.user._id,
            account: item.account,
         })),
         ...bill.toObject(),
      };
   });

   res.status(StatusCodes.OK).json({
      data: bills,
   });
};

const getBill = async (req, res) => {
   const billId = req.query.id;
   let bill = await queryBill(Bill, 'findById', billId);
   let atombills = await AtomBill.find({
      billId,
   }).populate({
      path: 'user',
      select: '_id username',
      model: 'User',
   });

   bill = {
      ...bill.toObject(),
      details: atombills.map((item) => ({
         username: item.user.username,
         userId: item.user._id,
         account: item.account,
      })),
   };
   res.status(StatusCodes.OK).json({
      data: bill,
   });
};

/**
 * 创建账单
 */
const createBill = async (req, res) => {
   const groupId = req.params.groupId;
   const userId = req.user.userId;

   const session = await mongoose.startSession();
   session.startTransaction();

   try {
      const { details, ...rest } = req.body;
      const bill = await Bill.create({
         ...rest,
         fromGroup: groupId,
         createdBy: userId,
      });
      await AtomBill.insertMany(
         details.map((item) => ({
            billId: bill._id,
            group: groupId,
            user: item.userId,
            account: item.account,
         }))
      );
      await session.commitTransaction();
      res.status(StatusCodes.OK).json({
         msg: '创建成功',
      });
   } catch (err) {
      await session.abortTransaction();
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: err });
   } finally {
      session.endSession();
   }
};

const updateBill = async (req, res) => {
   const billId = req.params.id;

   const session = await mongoose.startSession();
   session.startTransaction();
   try {
      const { details, ...rest } = req.body;
      const bill = await Bill.findByIdAndUpdate(
         mongoose.Types.ObjectId(billId),
         rest,
         {
            new: true,
            runValidators: true,
         }
      );
      // 删掉原来的，再插入
      await AtomBill.deleteMany({ billId });
      await AtomBill.insertMany(
         details.map((item) => ({
            billId,
            group: bill.fromGroup,
            user: item.userId,
            account: item.account,
         }))
      );
      await session.commitTransaction();
      res.status(StatusCodes.OK).json({ msg: '更新成功' });
   } catch (err) {
      await session.abortTransaction();
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: err });
   } finally {
      session.endSession();
   }
};

/**
 * 删除账单
 */
const removeBills = async (req, res) => {
   const ids = req.body.ids;
   const objIds = ids.map((id) => mongoose.Types.ObjectId(id));

   const session = await mongoose.startSession();
   session.startTransaction();

   try {
      await Bill.deleteMany({
         _id: { $in: objIds },
      });
      await AtomBill.deleteMany({
         billId: { $in: objIds },
      });
      await session.commitTransaction();
      res.status(StatusCodes.OK).json({ msg: '删除成功' });
   } catch (err) {
      await session.abortTransaction();
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: err });
   } finally {
      session.endSession();
   }
};

module.exports = {
   getBills,
   createBill,
   updateBill,
   removeBills,
   getBill,
};
